package com.mjf.utils;

import com.alibaba.fastjson.JSONObject;
import com.mjf.common.GmallConfig;
import redis.clients.jedis.Jedis;

import java.sql.Connection;
import java.sql.DriverManager;
import java.util.List;

/**
 * Phoenix 查询工具类
 *
 * 优化：
 * 1.首先到 redis 查询数据，如果查询到了返回数据，重置对应key的过期时间（24小时）
 * 2.如果 redis 中没有查到数据。则先到 phoenix 中查询数据，然后将数据写入 redis，最后将数据返回
 */
public class DimUtil {

    /**
     * 根据表名与id，查询对应的维度表
     * @param conn phoenix 连接
     * @param tableName 维度表
     * @param id id
     * @return 查询结果
     * @throws Exception
     */
    public static JSONObject getDimInfo(Connection conn, String tableName, String id) throws Exception {

        // 查询 Phoenix 之前，先查询 Redis 内容
        Jedis jedis = RedisUtil.getJedis();
        // DIM:DIM_USER_INFO:143
        String redisKey = "DIM:" + tableName + ":" + id;
        String dimInfoJsonStr = jedis.get(redisKey);

        if (dimInfoJsonStr != null) {
            // 重置过期时间
            jedis.expire(redisKey, 24 * 60 * 60);
            // 释放 redis 连接
            jedis.close();
            // 返回查询结果
            return JSONObject.parseObject(dimInfoJsonStr);
        }

        // 拼接查询语句
        String querySql = "select * from "
                + GmallConfig.HBASE_SCHEMA
                + "."
                + tableName
                + " where id = '"
                + id
                + "'";

        List<JSONObject> jsonObjects = JdbcUtil.queryList(conn, querySql, JSONObject.class, false);

        // 限定了 id,返回结果只有一个值
        JSONObject dimInfoJson = jsonObjects.get(0);

        // 将查询到的数据保存到 redis 中进行缓存
        jedis.set(redisKey, dimInfoJson.toJSONString());
        // 设置过期时间
        jedis.expire(redisKey, 24 * 60 * 60);

        // 释放 redis 连接
        jedis.close();

        return dimInfoJson;

    }

    /**
     * 为了保证数据一致性，在 phoenix 中的维度数据发生修改之后需要删除redis中缓存的过期数据
     * @param tableName 表名
     * @param id id
     */
    public static void delRedisDimInfo(String tableName, String id) {
        Jedis jedis = RedisUtil.getJedis();
        String redisKey = "DIM:" + tableName + ":" + id;
        jedis.del(redisKey);
        jedis.close();
    }

    public static void main(String[] args) throws Exception {
        Class.forName(GmallConfig.PHOENIX_DRIVER);
        Connection conn = DriverManager.getConnection(GmallConfig.PHOENIX_SERVER);

        long start = System.currentTimeMillis();
        System.out.println(getDimInfo(conn, "DIM_USER_INFO", "1641"));
        long end1 = System.currentTimeMillis();
        System.out.println(getDimInfo(conn, "DIM_USER_INFO", "1641"));
        long end2 = System.currentTimeMillis();
        System.out.println(getDimInfo(conn, "DIM_USER_INFO", "1641"));
        long end3 = System.currentTimeMillis();

        // 第一次读取需要访问zk，需要862ms
        System.out.println(end1 - start);
        // 第二次读取不需要访问zk，需要15ms，说明单并行度每1s可以处理70左右数据。需要进行优化，这个使用redis进行缓存
        System.out.println(end2 - end1);
        // 第三次读取 redis 时，时间降低到了 1ms
        System.out.println(end3 - end2);

        // 测试redis是否可以删除过期数据
//        System.out.println(getDimInfo(conn, "DIM_BASE_TRADEMARK", "13"));

        conn.close();
    }

}
